#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
-------------------------------------------------
   File Name：      email.py
   Remark :         企业级邮件通知工具类，支持发送文本和HTML格式邮件
-------------------------------------------------
"""


from __future__ import annotations

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from pydantic import BaseModel, Field, ValidationError
from typing import List, Optional
import logging

# 初始化日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)


class EmailConfig(BaseModel):
    smtp_server: str = Field(..., description="SMTP服务器地址")
    smtp_port: int = Field(..., description="SMTP服务器端口")
    username: str = Field(..., description="SMTP用户名")
    password: str = Field(..., description="SMTP密码")
    sender_email: str = Field(..., description="发送者邮箱地址")


class EmailNotifier:
    """
    企业级邮件通知工具类，支持发送文本和HTML格式邮件。
    """

    def __init__(self, email_config: EmailConfig):
        self.smtp_server = email_config.smtp_server
        self.smtp_port = email_config.smtp_port
        self.username = email_config.username
        self.password = email_config.password
        self.sender_email = email_config.sender_email

    def send_email(self, subject: str, body: str, to_emails: List[str], cc_emails: Optional[List[str]] = None,
                   bcc_emails: Optional[List[str]] = None, attachments: Optional[List[str]] = None,
                   is_html: bool = False) -> bool:
        """
        发送邮件
        :param subject: 邮件主题
        :param body: 邮件内容
        :param to_emails: 收件人列表
        :param cc_emails: 抄送人列表
        :param bcc_emails: 密送人列表
        :param attachments: 附件文件路径列表
        :param is_html: 是否为HTML格式
        :return: 发送是否成功
        """
        try:
            # 构建邮件信息
            message = MIMEMultipart()
            message['From'] = self.sender_email
            message['To'] = ", ".join(to_emails)
            message['Subject'] = subject
            if cc_emails:
                message['Cc'] = ", ".join(cc_emails)

            # 邮件正文部分
            if is_html:
                message.attach(MIMEText(body, 'html'))
            else:
                message.attach(MIMEText(body, 'plain'))

            # 附件部分
            if attachments:
                for attachment_path in attachments:
                    try:
                        with open(attachment_path, "rb") as attachment_file:
                            attachment = MIMEApplication(attachment_file.read(), _subtype="octet-stream")
                            attachment.add_header('Content-Disposition', 'attachment',
                                                  filename=attachment_path.split('/')[-1])
                            message.attach(attachment)
                    except FileNotFoundError:
                        logger.warning(f"附件 {attachment_path} 未找到，跳过该附件。")

            # 收件人组合
            recipients = to_emails
            if cc_emails:
                recipients += cc_emails
            if bcc_emails:
                recipients += bcc_emails

            # 发送邮件
            with smtplib.SMTP(self.smtp_server, self.smtp_port) as server:
                server.starttls()
                server.login(self.username, self.password)
                server.sendmail(self.sender_email, recipients, message.as_string())
                logger.info(f"邮件发送成功，收件人: {', '.join(to_emails)}")
                return True
        except smtplib.SMTPException as e:
            logger.error(f"邮件发送失败: {e}")
            return False


# 示例使用
if __name__ == '__main__':
    # 初始化邮件配置
    try:
        config = EmailConfig(
            smtp_server="smtp.example.com",
            smtp_port=587,
            username="your_username",
            password="your_password",
            sender_email="your_email@example.com"
        )
    except ValidationError as e:
        logger.error(f"配置校验失败: {e}")
        raise

    notifier = EmailNotifier(config)

    # 发送文本邮件
    notifier.send_email(
        subject="测试用例执行结果",                 # 邮件主题
        body="所有测试用例已成功通过！",            # 邮件内容
        to_emails=["recipient@example.com"],    # 收件人邮箱地址
        is_html=False                            # 是否为HTML格式
    )

    # 发送HTML邮件，附带附件
    notifier.send_email(
        subject="测试报告",
        body="<h3>测试结果</h3><p>请查看附件中的测试报告。</p>",
        to_emails=["recipient@example.com"],
        attachments=["/path/to/report.pdf"],
        is_html=True
    )
